package com.gewei.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.gewei.constant.MessageConstant;
import com.gewei.entity.Result;
import com.gewei.service.*;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 统计分析（图形报表操作）
 */
@RestController
@RequestMapping("/report")
public class ReportController {

    /**
     * 会员服务
     */
    @Reference
    private MemberService memberService;

    /**
     * 套餐服务
     */
    @Reference
    private SetmealService setmealService;

    /**
     * 会员年龄服务
     */
    @Reference
    private MemberAgeService memberAgeService;

    /**
     * 套餐数量服务
     */
    @Reference
    private SetmealCountService setmealCountService;

    /**
     * 报表服务
     */
    @Reference
    private ReportService reportService;

    /**
     * 会员数量统计折线图
     *
     * @return
     */
    @RequestMapping("/getMemberReport")
    public Result getMemberReport() {
        //  使用模拟数据测试对象格式是否能够转换为 Echarts 所需的数据格式
        /*Map<String, Object> map = new HashMap<>();
        //  月份
        List<String> months = new ArrayList();
        months.add("2016.01");
        months.add("2016.02");
        months.add("2016.03");
        months.add("2016.04");
        months.add("2016.05");
        months.add("2016.06");
        months.add("2016.07");
        months.add("2016.08");
        months.add("2016.09");
        months.add("2016.10");
        months.add("2016.11");
        months.add("2016.12");
        map.put("months", months);
        //  会员数量
        List<Integer> memberCount = new ArrayList<>();
        memberCount.add(101);
        memberCount.add(252);
        memberCount.add(383);
        memberCount.add(404);
        memberCount.add(535);
        memberCount.add(676);
        memberCount.add(727);
        memberCount.add(838);
        memberCount.add(939);
        memberCount.add(1010);
        memberCount.add(1111);
        memberCount.add(1212);
        map.put("memberCount", memberCount);
        return new Result(true, MessageConstant.GET_MEMBER_NUMBER_REPORT_SUCCESS, map);*/

        //  使用数据库查询到的数据测试对象格式是否能够转换为 Echarts 所需的数据格式
        Map<String, Object> map = new HashMap<>();
        //  月份（过去一年的）
        List<String> months = new ArrayList();
        //  获得日历对象，默认时间就是当前时间
        Calendar calendar = Calendar.getInstance();
        //  获得当前时间往前推 12 个月的时间
        calendar.add(Calendar.MONTH, -12);
        for (int i = 0; i < 12; i++) {
            //  获取当前 Calendar 时间往后推一个月日期
            calendar.add(Calendar.MONTH, 1);
            Date date = calendar.getTime();
            //  先格式化日期
            months.add(new SimpleDateFormat("yyyy.MM").format(date));
        }
        map.put("months", months);
        //  会员数量
        List<Integer> memberCount = memberService.findMemberCountByMonths(months);
        map.put("memberCount", memberCount);
        return new Result(true, MessageConstant.GET_MEMBER_NUMBER_REPORT_SUCCESS, map);
    }

    /**
     * 套餐预约占比统计饼形图
     *
     * @return
     */
    @RequestMapping("/getSetmealReport")
    public Result getSetmealReport() {
        //  使用模拟数据测试使用什么样的 Java 对象转换为饼形图所需的 Json 数据格式
        /*Map<String, Object> data = new HashMap<>();

        //  套餐名称
        List<String> setmealNames = new ArrayList<>();
        setmealNames.add("体检套餐");
        setmealNames.add("孕前检查套餐");
        data.put("setmealNames", setmealNames);

        //  套餐名称：套餐数量
        List<Map<String, Object>> setmealCount = new ArrayList<>();
        Map map1 = new HashMap();
        map1.put("name", "入职体检套餐");
        map1.put("value", 200);
        setmealCount.add(map1);

        Map map2 = new HashMap();
        map2.put("name", "孕前检查套餐");
        map2.put("value", 300);
        setmealCount.add(map2);
        data.put("setmealCount", setmealCount);

        return new Result(true, MessageConstant.GET_SETMEAL_COUNT_REPORT_SUCCESS, data);*/

        Map<String, Object> data = new HashMap<>();
        try {
            List<Map<String, Object>> setmealCount = setmealService.findSetMealCount();
            //  套餐名称：套餐数量
            data.put("setmealCount", setmealCount);

            List<String> setmealNames = new ArrayList<>();
            for (Map<String, Object> map : setmealCount) {
                //  套餐名称
                String name = (String) map.get("name");
                setmealNames.add(name);
            }
            data.put("setmealNames", setmealNames);
            //  返回结果
            return new Result(true, MessageConstant.GET_SETMEAL_COUNT_REPORT_SUCCESS, data);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.GET_SETMEAL_COUNT_REPORT_FAIL);
        }
    }

    /**
     * 会员年龄统计柱形图
     *
     * @return
     */
    @RequestMapping("/getMemberAgeReport")
    public Result getMemberAgeReport() {
        //  获得当前时间
        //  使用模拟数据测试对象格式是否能够转换为 echarts 所需的数据格式
        //  使用 Map 转换为 Jason
        Map<String, Object> map = new HashMap<>();
        List<String> ageRange = new ArrayList<>();
        ageRange.add("婴幼儿");
        ageRange.add("少儿");
        ageRange.add("青少年");
        ageRange.add("青年");
        ageRange.add("中年");
        ageRange.add("老年");
        map.put("ageRange", ageRange);

        List<Integer> agesCount = new ArrayList<>();
        agesCount.add(2);
        agesCount.add(2);
        agesCount.add(1);
        agesCount.add(8);
        agesCount.add(7);
        agesCount.add(1);
        map.put("agesCount", agesCount);
        return new Result(true, MessageConstant.GET_MEMBER_NUMBER_REPORT_SUCCESS, map);
    }

    /**
     * 体检收入统计饼形图
     *
     * @return
     */
    @RequestMapping("/getSetmealCountReport")
    public Result getSetmealCountReport() {
        //  使用模拟数据测试
        Map<String, Object> data = new HashMap<>();
        List<String> setmealSumNames = new ArrayList<>();
        setmealSumNames.add("入职无忧体检套餐(男女通用)");
        setmealSumNames.add("阳光爸妈升级肿瘤12项筛查体检套餐");
        setmealSumNames.add("珍爱高端升级肿瘤12项筛查");
        setmealSumNames.add("粉红珍爱升级检查(女)");
        setmealSumNames.add("儿童基本项检查");
        data.put("setmealSumNames", setmealSumNames);


        List<Map<String, Object>> setmealSumCount = new ArrayList<>();
        Map map1 = new HashMap();
        map1.put("name", "入职无忧体检套餐(男女通用)");
        map1.put("value", 1048);

        Map map2 = new HashMap();
        map2.put("name", "阳光爸妈升级肿瘤12项筛查体检套餐");
        map2.put("value", 735);

        Map map3 = new HashMap();
        map3.put("name", "珍爱高端升级肿瘤12项筛查");
        map3.put("value", 580);

        Map map4 = new HashMap();
        map4.put("name", "粉红珍爱升级检查(女)");
        map4.put("value", 484);

        Map map5 = new HashMap();
        map5.put("name", "儿童基本项检查");
        map5.put("value", 300);

        setmealSumCount.add(map1);
        setmealSumCount.add(map2);
        setmealSumCount.add(map3);
        setmealSumCount.add(map4);
        setmealSumCount.add(map5);

        data.put("setmealSumCount", setmealSumCount);
        return new Result(true, "体检收入统计查询成功", data);
    }

    /**
     * 运营数据统计
     *
     * @return
     */
    @RequestMapping("/getBusinessReportData")
    public Result getBusinessReportData() {
        //  使用模拟数据测试流程是否可以正常展示
        /*HashMap<String, Object> data = new HashMap<>();
        //  会员数据统计
        data.put("reportDate", "2022.04.07");
        data.put("todayNewMember", "100");
        data.put("totalMember", "20000");
        data.put("thisWeekNewMember", "300");
        data.put("thisMonthNewMember", "500");
        //  预约到诊数据统计
        data.put("todayOrderNumber", "150");
        data.put("todayVisitsNumber", "100");
        data.put("thisWeekOrderNumber", "300");
        data.put("thisWeekVisitsNumber", "290");
        data.put("thisMonthOrderNumber", "500");
        data.put("thisMonthVisitsNumber", "400");
        //  热门套餐
        List<Map<String, Object>> hotSetmeal = new ArrayList();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("name", "阳光爸妈升级肿瘤12项筛查（男女单人）体检套餐");
        map1.put("setmeal_count", 200);
        map1.put("proportion", 0.5);
        Map<String, Object> map2 = new HashMap<>();
        map2.put("name", "阳光爸妈升级肿瘤12项筛查体检套餐");
        map2.put("setmeal_count", 200);
        map2.put("proportion", 0.5);
        hotSetmeal.add(map1);
        hotSetmeal.add(map2);
        //  封装结果
        data.put("hotSetmeal", hotSetmeal);
        return new Result(true, MessageConstant.GET_BUSINESS_REPORT_FAIL, data);*/
        try {
            Map<String, Object> data = reportService.getBusinessReportData();
            return new Result(true, MessageConstant.GET_BUSINESS_REPORT_SUCCESS, data);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL);
        }
    }

    /**
     * 导出 Excel 报表（运营数据）
     *  基于 POI 将数据写入到 Excel 中并通过输出流下载到客户端
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/exportBusinessReport")
    public Result exportBusinessReport(HttpServletRequest request, HttpServletResponse response) {
        try {
            //  远程调用报表服务获取报表数据
            Map<String, Object> result = reportService.getBusinessReportData();
            //  取出返回结果数据，准备将报表数据写入到 Excel 文件中
            String reportDate = (String) result.get("reportDate");
            Integer todayNewMember = (Integer) result.get("todayNewMember");
            Integer totalMember = (Integer) result.get("totalMember");
            Integer thisWeekNewMember = (Integer) result.get("thisWeekNewMember");
            Integer thisMonthNewMember = (Integer) result.get("thisMonthNewMember");
            Integer todayOrderNumber = (Integer) result.get("todayOrderNumber");
            Integer thisWeekOrderNumber = (Integer) result.get("thisWeekOrderNumber");
            Integer thisMonthOrderNumber = (Integer) result.get("thisMonthOrderNumber");
            Integer todayVisitsNumber = (Integer) result.get("todayVisitsNumber");
            Integer thisWeekVisitsNumber = (Integer) result.get("thisWeekVisitsNumber");
            Integer thisMonthVisitsNumber = (Integer) result.get("thisMonthVisitsNumber");
            List<Map> hotSetmeal = (List<Map>) result.get("hotSetmeal");

            //  动态方式获得 Excel 模版文件在磁盘上的绝对路径，separator：分隔符
            String temlateRealPath = request.getSession().getServletContext().getRealPath("template") + File.separator + "report_template.xlsx";
            //  基于提供的 Excel 模板文件 report_template.xlsx 在内存中创建一个 Excel 表格对象
            XSSFWorkbook excel = new XSSFWorkbook(new FileInputStream(new File(temlateRealPath)));
            //  读取第 1 个工作表
            XSSFSheet sheet = excel.getSheetAt(0);
            //  获得第 3 行
            XSSFRow row = sheet.getRow(2);
            //  日期
            row.getCell(5).setCellValue(reportDate);

            row = sheet.getRow(4);
            //  新增会员数（本日）
            row.getCell(5).setCellValue(todayNewMember);
            //  总会员数
            row.getCell(7).setCellValue(totalMember);

            row = sheet.getRow(5);
            //  本周新增会员数
            row.getCell(5).setCellValue(thisWeekNewMember);
            //  本月新增会员数
            row.getCell(7).setCellValue(thisMonthNewMember);

            row = sheet.getRow(7);
            //  今日预约数
            row.getCell(5).setCellValue(todayOrderNumber);
            //  今日到诊数
            row.getCell(7).setCellValue(todayVisitsNumber);

            row = sheet.getRow(8);
            //  本周预约数
            row.getCell(5).setCellValue(thisWeekOrderNumber);
            //  本周到诊数
            row.getCell(7).setCellValue(thisWeekVisitsNumber);

            row = sheet.getRow(9);
            //  本月预约数
            row.getCell(5).setCellValue(thisMonthOrderNumber);
            //  本月到诊数
            row.getCell(7).setCellValue(thisMonthVisitsNumber);

            int rowNum = 12;
            //  热门套餐
            for (Map map : hotSetmeal) {
                String name = (String) map.get("name");
                Long setmeal_count = (Long) map.get("setmeal_count");
                BigDecimal proportion = (BigDecimal) map.get("proportion");
                row = sheet.getRow(rowNum++);
                //  套餐名称
                row.getCell(4).setCellValue(name);
                //  预约数量
                row.getCell(5).setCellValue(setmeal_count);
                //  占比
                row.getCell(6).setCellValue(proportion.doubleValue());
            }

            //  使用输出流进行表格下载,基于浏览器作为客户端下载
            OutputStream out = response.getOutputStream();
            //  "application/vnd.ms-excel" 代表的是 Excel 文件类型
            response.setContentType("application/vnd.ms-excel");
            //  指定以附件形式进行下载
            response.setHeader("content-Disposition", "attachment;filename=report.xlsx");
            excel.write(out);

            out.flush();
            out.close();
            excel.close();

            return null;
        } catch (Exception e) {
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL);
        }
    }
}